/*!
  * @file     base_timer.c
  *
  * @brief    系统计时器
  *
  * @company   
  *
  * @author   不咸不要钱
  *
  * @note     
  *
  * @version  V1.2
  *
  * @Software  
  *
  * @par URL  
  *              
  *
  * @date     2019/07/15
  */ 
#include "base_timer.h"

/** 
  * @brief 一个时间结构体
  * @note  内部调用
  */
typedef struct{
    uint32_t ulTickPerMicrosecond;                  /*!<每us tick计数值         */
    uint32_t ulTickPerMillisecond;                  /*!<每ms tick计数值         */
    uint32_t ulTickPerHandler;                      /*!<每？ticks 定时器中断一次*/
    volatile uint64_t ullTicks;                     /*!<当前ticks               */
    uint32_t ulDelayOffSet;                         /*!<函数零偏                */
}BaseTimerParame_t;

/** 保存定时器参数 */
static BaseTimerParame_t s_tTimer;

#if defined(SOFT_TIMER_ENABLE) && (SOFT_TIMER_ENABLE == 1)
static void stimer_ticks(void);
#endif

/*!
  * @brief    定时器tick自增
  *
  * @param    无
  *
  * @return   无
  *
  * @note     需要在定时器中断服务函数中调用 btimer_ticks(); 
  *
  * @see      无
  *
  * @date     2019/07/15
  */
void btimer_ticks(void)
{
    s_tTimer.ullTicks     += s_tTimer.ulTickPerHandler;
    
    #if defined(SOFT_TIMER_ENABLE) && (SOFT_TIMER_ENABLE == 1)
        stimer_ticks();    
    #endif
}

/*!
  * @brief    初始化定时器
  *
  * @param    clock:  定时器时钟 clock要大于等于 1M
  * @param    ticks:  定时器每s中断ticks次 
  *
  * @return   无
  *
  * @note     
  *
  * @see      btimer_init(72000000, 1000);  
  *
  * @date     2019/07/15
  */
void btimer_init(uint32_t clock, uint16_t ticks)
{
    
    if(clock < 1000000ul)
    {
        /* 定时器频率 小于1MHz  每us tick计数值 固定为1 
           注意：定时器频率过低，使用us相关函数时会不准确 */
        s_tTimer.ulTickPerMicrosecond = 1;
    }
    else
    {
        s_tTimer.ulTickPerMicrosecond = clock / 1000000ul;
    }
    
    if(clock < 1000)
    {
        /* 定时器频率 小于1KHz  
           注意：定时器频率过低 */
        while(1);
    }
    else
    {
        s_tTimer.ulTickPerMillisecond = clock / 1000;
    }
    
    s_tTimer.ullTicks = 0;
    s_tTimer.ulTickPerHandler = clock / ticks;
    s_tTimer.ulDelayOffSet = 0;
    
    btimer_port_init(clock, ticks);
    
    /* 去零偏 */
    uint32_t currentTicks1 = 0, currentTicks2 = 0;
    for(int i = 0; i < 1000; i++)
    {
        currentTicks1 = btimer_get_ticks();
        btimer_delay_us(1);
        currentTicks2 = btimer_get_ticks();
        s_tTimer.ulDelayOffSet += (currentTicks2 - currentTicks1 - s_tTimer.ulTickPerMicrosecond);
    }
    s_tTimer.ulDelayOffSet = (s_tTimer.ulDelayOffSet + 500)/1000;
}


/*!
  * @brief    关闭定时器
  *
  * @param    无
  *
  * @return   无
  *
  * @note     
  *
  * @see      BaseTimerDeInit();  
  *
  * @date     2019/07/15
  */
void btimer_deinit(void)
{
    btimer_port_deinit();
}

/*!
  * @brief    获取当前tick值
  *
  * @param    无
  *
  * @return   从定时器初始化到当前的ticks
  *
  * @note     
  *
  * @see      
  *
  * @date     2019/07/15
  */
uint64_t btimer_get_ticks(void)
{
    uint64_t ticks = 0;
    uint32_t timerValue = 0;
    do
    {
        ticks = s_tTimer.ullTicks;
        timerValue = btimer_port_get_ticks();
        
    }while(ticks != s_tTimer.ullTicks);
    return ticks + timerValue;
}

/*!
  * @brief    获取当前us值
  *
  * @param    无
  *
  * @return   从定时器初始化到当前的us
  *
  * @note     uint64 除法非常耗时  stm32F1xx 做一次 uint64除法大概需要50us
  *
  * @see      
  *
  * @date     2019/07/15
  */
uint32_t btimer_get_us(void)
{
    return btimer_get_ticks()/s_tTimer.ulTickPerMicrosecond;
}



/*!
  * @brief    获取当前ms值
  *
  * @param    无
  *
  * @return   从定时器初始化到当前的ms
  *
  * @note     uint64 除法非常耗时  stm32F1xx 做一次 uint64除法大概需要50us
  *
  * @see      
  *
  * @date     2019/07/15
  */
uint32_t btimer_get_ms(void)
{
    return btimer_get_ticks()/s_tTimer.ulTickPerMillisecond;
}



/*!
  * @brief    延时
  *
  * @param    ticks ： 要延时的ticks
  *
  * @return   无
  *
  * @note     
  *
  * @see      
  *
  * @date     2019/07/15
  */
void btimer_delay_ticks(uint32_t ticks)
{
    uint64_t end = btimer_get_ticks() + ticks - s_tTimer.ulDelayOffSet;
    
    while(btimer_get_ticks() <= end);
}

/*!
  * @brief    延时
  *
  * @param    us ： 要延时的us
  *
  * @return   无
  *
  * @note     
  *
  * @see      
  *
  * @date     2019/07/15
  */
void btimer_delay_us(uint32_t us)
{
    uint64_t end = btimer_get_ticks() + us * s_tTimer.ulTickPerMicrosecond - s_tTimer.ulDelayOffSet;
    
    while(btimer_get_ticks() <= end);
}

/*!
  * @brief    延时
  *
  * @param    ms ： 要延时的ms
  *
  * @return   无
  *
  * @note     
  *
  * @see      
  *
  * @date     2019/07/15
  */
void btimer_delay_ms(uint32_t ms)
{
    uint64_t end = btimer_get_ticks() + ms * s_tTimer.ulTickPerMillisecond - s_tTimer.ulDelayOffSet;
    
    while(btimer_get_ticks() <= end);
}


#if defined(SOFT_TIMER_ENABLE) && (SOFT_TIMER_ENABLE == 1)

/** 指向软件定时器驱动链表头节点 */
static Stimer_t * s_stimer_head = 0;

/*!
  * @brief    软件定时器节拍处理
  *
  * @param    无
  *
  * @return   无
  *
  * @note     需要周期性调用该函数  软件定时器ticks均以该周期为单位 
  *
  * @see      
  *
  * @date     2019/07/15
  */
static void stimer_ticks(void)
{
    Stimer_t * node = s_stimer_head;
    
    while(node)
    {
        if(node->ucCounter > 0)
        {  
            if(-- node->ulTicks == 0)
            {
                if(node->ucCounter != COUNTER_MAX)
                {
                    node->ucCounter--;
                }

                node->ulTicks = node->ulPerLoad;
                node->ucFlag  = 1;
                
                if(node->stimerCallback != 0)
                {
                    node->stimerCallback((void *)node);
                }
                
                if(node->ucCounter == 0)
                {
                    stimer_stop(node);
                }
            }
        }
        else
        {
            stimer_stop(node);
        } 
        
        node = node->ptNextTimer;
    }
}    

/*!
  * @brief    软件定时器初始化
  *
  * @param    stimer：软件定时器
  * @param    ticks ：软件定时器定时时间
  * @param    count ：软件定时器定时次数  如果为0xFF 则为永久
  * @param    cb    ：软件定时器溢出回调函数
  *
  * @return   无
  *
  * @note     cb 回调函数会在 btimer_ticks() 中执行，而 btimer_ticks() 一般在中断服务函数中，因此定时器溢出回调函数尽量快进快出
  *
  * @see      
  *
  * @date     2019/07/15
  */
void stimer_init(Stimer_t * stimer, uint16_t ticks, uint8_t count, stimerCallback_t cb)
{
    stimer_port_lock();
    
    stimer->ulTicks   = ticks;
    stimer->ulPerLoad = ticks;
    stimer->ucCounter = count;
    stimer->ucFlag    = 0;
    stimer->stimerCallback = cb;
    
    stimer_port_unlock();
}

/*!
  * @brief    开启软件定时器
  *
  * @param    stimer：软件定时器
  *
  * @return   无
  *
  * @note     将软件定时器添加到链表上
  *
  * @see      
  *
  * @date     2019/07/15
  */
void stimer_start(Stimer_t * stimer)
{
    stimer_port_lock();
  
    /* 防止重复 */
    Stimer_t * node = s_stimer_head;

    while(node)
    {
        if(node == stimer)
        {
            stimer_port_unlock();
            return;
        }
        else
        {
            node = node->ptNextTimer;
        }   
    }

    stimer->ptNextTimer  = s_stimer_head;
    s_stimer_head        = stimer;
    
    stimer_port_unlock();
}

/*!
  * @brief    停止软件定时器
  *
  * @param    stimer：软件定时器
  *
  * @return   无
  *
  * @note     将软件定时器从定时器链表上移除
  *
  * @see      
  *
  * @date     2019/07/15
  */
void stimer_stop(Stimer_t * stimer)
{
    Stimer_t** curr;
    for(curr = &s_stimer_head; *curr; ) 
    {
        Stimer_t* entry = *curr;
        if (entry == stimer) 
        {
            stimer_port_lock();
                
            *curr = entry->ptNextTimer;
                
            stimer_port_unlock();
            return;
        } 
        else
        {
            curr = &entry->ptNextTimer;
        }   	
	}
}

/*!
  * @brief    停止软件定时器超时
  *
  * @param    stimer：软件定时器
  *
  * @return   无
  *
  * @note     调用后会自动清除超时标志位
  *
  * @see      
  *
  * @date     2019/07/15
  */
uint8_t stimer_is_timeout(Stimer_t * stimer)
{
    uint8_t flag = stimer->ucFlag;
    
    stimer_port_lock();
    
    stimer->ucFlag = 0;
    
    stimer_port_unlock();
    
    return flag;
}
#endif
